using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Hope;
using GoShared;
/// <summary>
/// <para>教学使用的UI元素管理类</para>
/// </summary>
public class TutorialUIManager : GeneralUIManager<TutorialUIManager>
{
	/// <summary>
	/// <para>该管理类在通用UI元素中的优先级</para>
	/// </summary>
	protected override Priority GetPriority()
	{
		return Priority.Tutorial;
	}

	#region 显示对话框

	/// <summary>
	/// <para>对话框对象的RectTransform组件</para>
	/// </summary>
	RectTransform _dialog = null;

	/// <summary>
	/// <para>角色类型</para>
	/// </summary>
	public enum CharacterType
	{
		Char1,
		Char2,
		Char3,
		Char4,

		Count,
	}

	/// <summary>
	/// <para>角色对象缓存</para>
	/// </summary>
	GameObject[] _characters = new GameObject[(int)CharacterType.Count];

	/// <summary>
	/// <para>对话框类型，Bottom为底部对话框，Anywhere为自定义位置的对话框</para>
	/// </summary>
	public enum DialogType
	{
		Bottom,
		Anywhere,
	}

	/// <summary>
	/// <para>角色位置，目前支持左、右、左下、右下</para>
	/// </summary>
	public enum CharacterPos
	{
		Left,
		Right,
		BottomLeft,
		BottomRight,

		Count,
	}

	/// <summary>
	/// <para>显示一个对话框</para>
	/// </summary>
	/// <param name="type">对话框类型</param>
	/// <param name="cPos">角色位置</param>
	/// <param name="chType">角色类型</param>
	/// <param name="text">显示文本</param>
	/// <param name="displayContinue">是否显示“点击继续”图标</param>
	/// <param name="rectPanel">对话框面板大小，数值为屏幕比例</param>
	/// <param name="hideChar">是否隐藏角色</param>
	public GameObject ShowDialog(DialogType type, CharacterPos cPos, CharacterType chType, string text, bool displayContinue, Rect rectPanel, bool hideChar = false)
	{
		if (_dialog == null) {
			var go = Instantiate(Resources.Load<GameObject>("Prefabs/Tutorial/Dialog/Dialog")) as GameObject;
			_dialog = go.transform as RectTransform;
            _dialog.gameObject.AddComponent<TutorialClick>();
            _dialog.SetParent(transform, false);
			_dialog.localScale = Vector3.one;
		}
		_dialog.gameObject.SetActive(false);

		RectTransform root = _dialog.Find(type.ToString()) as RectTransform;
		Text contentText = null;
		for (int i = 0; i < _dialog.childCount; ++i) {
			var go = _dialog.GetChild(i).gameObject;
			go.SetActive(type.ToString() == go.name);
			if (type.ToString() == go.name) {
				contentText = go.transform.Find("Background/Text").GetComponent<Text>();
			}
		}
		if (contentText)
			contentText.text = text;
		Transform rtrans = null;

		switch (type) {
			case DialogType.Anywhere:
				root.anchorMin = new Vector2(rectPanel.xMin, rectPanel.yMin);
				root.anchorMax = new Vector2(rectPanel.xMax, rectPanel.yMax);

				for (CharacterPos i = 0; i < CharacterPos.Count; ++i) {
					var parentTrans = root.Find("Background/" + i.ToString() + "/Char");
					parentTrans.parent.gameObject.SetActive(i == cPos && !hideChar);
					if (i == cPos) {
						rtrans = parentTrans;
						var anchorPos = (rtrans.parent as RectTransform).anchoredPosition;
						Rect rootRect = UIUtils.GetRectInCanvas(GetCanvas(), root.Find("Background") as RectTransform);
						switch (cPos) {
							case CharacterPos.BottomLeft:
								(rtrans.parent as RectTransform).anchoredPosition = new Vector2(rootRect.width * -.3f, anchorPos.y);
								break;
							case CharacterPos.BottomRight:
								(rtrans.parent as RectTransform).anchoredPosition = new Vector2(rootRect.width * .3f, anchorPos.y);
								break;
						}
					}
				}
				root.Find("Background/ClickContinuePic").gameObject.SetActive(displayContinue);
				break;
			case DialogType.Bottom:
				rtrans = root.Find("Background/Char");
				root.Find("Background/ClickContinuePic").gameObject.SetActive(displayContinue);
				break;
		}
		for (int i = 0; i < _characters.Length; ++i) {
			if ((int)chType == i && !hideChar) {
				if (_characters[i] == null) {
					_characters[i] = Instantiate(Resources.Load<GameObject>("Prefabs/Tutorial/Dialog/" + chType.ToString()), rtrans, false);
				} else {
					_characters[i].transform.SetParent(rtrans, false);
					_characters[i].SetActive(true);
				}
			} else {
				if (_characters[i])
					_characters[i].SetActive(false);
			}
		}

		_dialog.gameObject.SetActive(true);
        return _dialog.gameObject;
	}

	/// <summary>
	/// <para>隐藏当前对话框</para>
	/// </summary>
	public void HideDialog()
	{
		if (_dialog != null) {
			_dialog.gameObject.SetActive(false);
		}
	}

	/// <summary>
	/// <para>当前是否有对话框</para>
	/// </summary>
	public bool HasDialog()
	{
		return _dialog != null && _dialog.gameObject.activeInHierarchy;
	}

    #endregion

    #region 泡泡框
    RectTransform tutorialPromptBox;

    public enum PromptType
    {
        Left,
        Right,
        Up,
        Down,
        Hide,
    }

    #endregion

    #region 焦点遮罩

    /// <summary>
    /// <para>遮罩对象</para>
    /// </summary>
    RectTransform[] _focusMasks = new RectTransform[4];

	/// <summary>
	/// <para>显示一个遮罩</para>
	/// </summary>
	/// <param name="focusRectTf">遮罩不覆盖的UI元素的RectTransform组件</param>
	/// <param name="canvas">所属的canvas对象</param>
	/// <param name="_maskAlpha">遮罩的透明度</param>
	public void ShowFocusMasks(RectTransform focusRectTf, Canvas canvas, float _maskAlpha = .4f)
	{
		Rect focusRect = focusRectTf.rect;
		for (int i = 0; i < _focusMasks.Length; ++i) {
			if (_focusMasks[i] == null) {
				var go = new GameObject();
				go.name = "FocusMask" + (i + 1);
				var image = go.AddComponent<Image>();
				image.color = new Color(0, 0, 0, _maskAlpha);
				_focusMasks[i] = go.transform as RectTransform;
				_focusMasks[i].SetParent(transform);
				_focusMasks[i].localScale = Vector3.one;
				_focusMasks[i].gameObject.SetActive(false);
			} else
				_focusMasks[i].GetComponent<Image>().color = new Color(0, 0, 0, _maskAlpha);
		}

		float width = 6000f, height = 6000f;
		var pageCanvasScale = canvas.transform.localScale.x;
		var tutorialCanvasScale = transform.parent.localScale.x;
		float pt = pageCanvasScale / tutorialCanvasScale;
		for (int i = 0; i < _focusMasks.Length; ++i) {
			Vector2 newCenter = UIUtils.GetCenterPosInWorldFromRectTf(focusRectTf, pageCanvasScale);
			switch (i) {
				case 0:
					_focusMasks[i].sizeDelta = new Vector2(width, height);
					newCenter += Vector2.left * (width * tutorialCanvasScale + focusRect.width * focusRectTf.localScale.x * pageCanvasScale) * .5f;
					break;
				case 1:
					_focusMasks[i].sizeDelta = new Vector2(focusRect.width * focusRectTf.localScale.x * pt, height);
					newCenter += Vector2.up * (height * tutorialCanvasScale + focusRect.height * focusRectTf.localScale.y * pageCanvasScale) * .5f;
					break;
				case 2:
					_focusMasks[i].sizeDelta = new Vector2(width, height);
					newCenter += Vector2.right * (width * tutorialCanvasScale + focusRect.width * focusRectTf.localScale.x * pageCanvasScale) * .5f;
					break;
				case 3:
				default:
					_focusMasks[i].sizeDelta = new Vector2(focusRect.width * focusRectTf.localScale.x * pt, height);
					newCenter += Vector2.down * (height * tutorialCanvasScale + focusRect.height * focusRectTf.localScale.y * pageCanvasScale) * .5f;
					break;
			}
			_focusMasks[i].position = newCenter;
		}

		for (int i = 0; i < _focusMasks.Length; ++i) {
			_focusMasks[i].gameObject.SetActive(true);
			_focusMasks[i].SetAsFirstSibling();
		}
	}

	/// <summary>
	/// <para>隐藏一个遮罩</para>
	/// </summary>
	public void HideFocusMasks()
	{
		for (int i = 0; i < _focusMasks.Length; ++i) {
			if (_focusMasks[i] != null) {
				_focusMasks[i].gameObject.SetActive(false);
			}
		}
	}

	/// <summary>
	/// <para>当前是否存在遮罩</para>
	/// </summary>
	public bool HasFocusMasks()
	{
		for (int i = 0; i < _focusMasks.Length; ++i) {
			if (_focusMasks[i] != null && _focusMasks[i].gameObject.activeInHierarchy) {
				return true;
			}
		}

		return false;
	}

	#endregion
    
	#region 建筑遮罩

    public RectTransform GetTempForBuildingMask(BoxCollider collider, Canvas canvas)
    {
        RectTransform canvasRect = canvas.transform as RectTransform;
        var TempImageTrans = GameObject.Instantiate(Resources.Load<GameObject>("Prefabs/Tutorial/TempImage")).GetComponent<RectTransform>();
        TempImageTrans.SetParent(transform);

        Vector3 size = collider.size;
        Vector3 scale = collider.transform.localScale;
        size.x *= scale.x;
        size.y *= scale.y;
        size.z *= scale.z;
        Vector3 halfSize = size / 2;
        Vector3 position = collider.transform.position;
        Vector3 pos1 = position + collider.center + halfSize;
        Vector3 pos2 = position + collider.center - halfSize;
        Vector3 pos3 = pos1, pos4 = pos1, pos5 = pos1;
        Vector3 pos6 = pos2, pos7 = pos2, pos8 = pos2;
        pos3.x -= size.x;
        pos4.y -= size.y;
        pos5.z -= size.z;

        pos6.x += size.x;
        pos7.y += size.y;
        pos8.z += size.z;

        List<Vector3> v3List = new List<Vector3>() { pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8 };
        Camera main = Camera.main;
        var v3 = main.WorldToScreenPoint(v3List[0]);
        float xmin = v3.x, xmax = v3.x, ymin = v3.y, ymax = v3.y;
        for (int i = 1; i < v3List.Count; i++)
        {
            v3 = main.WorldToScreenPoint(v3List[i]);
            if (v3.x > xmax)
            {
                xmax = v3.x;
            }
            if (v3.x < xmin)
            {
                xmin = v3.x;
            }
            if (v3.y > ymax)
            {
                ymax = v3.y;
            }
            if (v3.y < ymin)
            {
                ymin = v3.y;
            }
        }

        Vector2 canvasScale = canvas.transform.localScale;
        Vector2 pos =  main.WorldToScreenPoint(collider.transform.position);
        pos.x = pos.x / canvasScale.x;
        pos.y = pos.y / canvasScale.y;
        pos -= canvasRect.sizeDelta / 2;
        TempImageTrans.anchoredPosition = pos;
        Rect ret = Rect.MinMaxRect(xmin, ymin, xmax, ymax);
        TempImageTrans.sizeDelta = new Vector2(ret.width, ret.height);
        TempImageTrans.SetAsFirstSibling();
        return TempImageTrans;
    }

	#endregion

	#region 建筑遮罩

	/// <summary>
	/// Mask
	/// </summary>
	GameObject _fullMask = null;

	public GameObject ShowFullMask()
	{
		if (_fullMask == null) {
			CreateFullMask();
		}
		_fullMask.transform.SetAsFirstSibling();
		_fullMask.SetActive(true);
		return _fullMask;
	}

	public void CreateFullMask()
	{
		if (_fullMask == null) {
			_fullMask = new GameObject("FullMask");
			var rectTrans = _fullMask.AddComponent<RectTransform>();
			var image = _fullMask.gameObject.AddComponent<Image>();
			image.color = new Vector4(0, 0, 0, 0);
			_fullMask.transform.SetParent(transform);
			rectTrans.anchorMax = new Vector2(1, 1);
			rectTrans.anchorMin = new Vector2(0, 0);
			rectTrans.anchoredPosition = new Vector2(0, 0);
		}
	}

	public void HideFullMask()
	{
		if (_fullMask) {
			_fullMask.gameObject.SetActive(false);
		}
	}

	public bool HasFullMask()
	{
		return _fullMask != null && _fullMask.gameObject.activeInHierarchy;
	}

	#endregion

	#region 可交互的全屏遮罩

	RectTransform _interactableMask = null;

	public void ShowInteractableFullScreenMask(TutorialEventNode eventNode, float _maskAlpha = 0.4f)
	{
		Image image;
		if (_interactableMask == null) {
			var go = new GameObject();
			go.name = "FullScreenMask";
			image = go.AddComponent<Image>();
			_interactableMask = go.transform as RectTransform;
			_interactableMask.SetParent(transform, false);
			go.SetActive(false);
			float width = 6000f, height = 6000f;
			_interactableMask.sizeDelta = new Vector2(width, height);
		} else {
			image = _interactableMask.gameObject.GetComponent<Image>();
		}
		image.color = new Color(0, 0, 0, _maskAlpha);
		if (eventNode != null) {
			var tc = _interactableMask.gameObject.AddComponent<TutorialClick>();
			tc.Node = eventNode;
			image.raycastTarget = true;
		} else {
			image.raycastTarget = false;
		}

		_interactableMask.gameObject.SetActive(true);

		if (HasFullMask()) {
			_interactableMask.SetAsFirstSibling();
			_fullMask.transform.SetAsFirstSibling();
		} else 
			_interactableMask.SetAsFirstSibling();
	}

	public void HideInteractableFullScreenMask()
	{
		if (_interactableMask) {
			_interactableMask.gameObject.SetActive(false);
		}
	}

	public bool HasInteractableFullScreenMask()
	{
		return _interactableMask != null && _interactableMask.gameObject.activeInHierarchy;
	}

	#endregion

	#region 焦点框

	/// <summary>
	/// <para>焦点框对象</para>
	/// </summary>
	public RectTransform _focusFrame = null;

	/// <summary>
	/// <para>显示一个焦点框</para>
	/// </summary>
	/// <param name="focusRectTf">遮罩不覆盖的UI元素的RectTransform组件</param>
	/// <param name="canvas">所属的canvas对象</param>
	public void ShowFocusFrame(RectTransform focusRectTf, Canvas canvas)
	{
		if (_focusFrame == null) {
			var go = Instantiate(Resources.Load<GameObject>("Prefabs/Tutorial/Focus/FocusFrame")) as GameObject;
			_focusFrame = go.transform as RectTransform;
			_focusFrame.gameObject.SetActive(false);
			_focusFrame.SetParent(transform);
			_focusFrame.localScale = Vector3.one;
		}
		_focusFrame.localScale = focusRectTf.localScale;
		var pageCanvasScale = canvas.transform.localScale.x;
		var tutorialCanvasScale = transform.parent.localScale.x;
		_focusFrame.position = UIUtils.GetCenterPosInWorldFromRectTf(focusRectTf, pageCanvasScale);
		float pt = pageCanvasScale / tutorialCanvasScale;
		_focusFrame.sizeDelta = new Vector2(focusRectTf.rect.size.x * pt + 45, focusRectTf.rect.size.y * pt + 45);

		_focusFrame.gameObject.SetActive(true);
	}

	/// <summary>
	/// <para>隐藏一个焦点框</para>
	/// </summary>
	public void HideFocusFrame()
	{
		if (_focusFrame) {
			_focusFrame.gameObject.SetActive(false);
		}
	}

	/// <summary>
	/// <para>当前是否存在焦点框</para>
	/// </summary>
	public bool HasFocusFrame()
	{
		return _focusFrame != null && _focusFrame.gameObject.activeInHierarchy;
	}

	#endregion

	#region 指示箭头

	/// <summary>
	/// <para>指示箭头对象</para>
	/// </summary>
	RectTransform _focusPointerRect = null;
    TutorialPointer _focusPointer = null;

    /// <summary>
    /// <para>显示一个指示箭头</para>
    /// </summary>
    /// <param name="focusRectTf">遮罩不覆盖的UI元素的RectTransform组件</param>
    /// <param name="canvas">所属的canvas对象</param>
    /// <param name="angle">箭头指向角度</param>
    /// <param name="isMove">箭头是否播放移动动画</param>
    /// <param name="moveRange">移动范围</param>
    /// <param name="isPingPong">是否PingPong动画</param>
    public void ShowFocusPointer(RectTransform focusRectTf, Canvas canvas, float angle, bool isMove, float moveRange, bool isPingPong = true)
	{
		StartCoroutine(ShowFocusPointerSub(focusRectTf, canvas, angle, isMove, moveRange, isPingPong));
	}

	IEnumerator ShowFocusPointerSub(RectTransform focusRectTf, Canvas canvas, float angle, bool isMove, float moveRange, bool isPingPong = true)
	{
		Vector2 moveDirection = default(Vector2);
		if (isMove)
			moveDirection = UIUtils.GetNormalizedFromAngle(angle);
		if (_focusPointer == null) {
            _focusPointer = Instantiate(Resources.Load<TutorialPointer>("Prefabs/Tutorial/Focus/TutorialPointer")) as TutorialPointer;
			_focusPointerRect = _focusPointer.transform as RectTransform;
			_focusPointerRect.gameObject.SetActive(false);
			_focusPointerRect.SetParent(transform);
			_focusPointerRect.localScale = Vector3.one;
		}
        //_focusPointer.StartPoint();
        Vector2 pivotPos = UIUtils.GetOctagonalPosOfRectByAngleInWorld(focusRectTf, angle, canvas.transform.localScale);

        _focusPointerRect.position = focusRectTf.position;

		angle = UIUtils.NormalizedAngle(angle);
		_focusPointerRect.localScale = new Vector3(1, angle > 90 && angle < 270 ? 1 : -1, 1);
		_focusPointerRect.eulerAngles = new Vector3(0, 0, angle);

		yield return null;
		_focusPointerRect.gameObject.SetActive(true);

		if (isMove) {
			Vector2 targetPosition = (Vector2)_focusPointerRect.position - moveDirection * moveRange * canvas.transform.localScale.x;
			GameObjectMove(_focusPointerRect.gameObject, _focusPointerRect.position, targetPosition, 1, isPingPong);
		}
	}

	/// <summary>
	/// <para>隐藏一个指示箭头</para>
	/// </summary>
	public void HideFocusPointer()
	{
		if (_focusPointerRect) {
			_focusPointerRect.gameObject.SetActive(false);
            _focusPointer.Stop();
        }
	}

	/// <summary>
	/// <para>当前是否存在指示箭头</para>
	/// </summary>
	public bool HasFocusPointer()
	{
		return _focusPointerRect != null && _focusPointerRect.gameObject.activeInHierarchy;
	}


    /// <summary>
	/// <para>指示箭头对象</para>
	/// </summary>
	RectTransform new_focusPointerRect = null;
    public TutorialPointer new_focusPointer = null;

    /// <summary>
    /// <para>显示一个指示箭头</para>
    /// </summary>
    /// <param name="focusRectTf">遮罩不覆盖的UI元素的RectTransform组件</param>
    /// <param name="canvas">所属的canvas对象</param>
    /// <param name="angle">箭头指向角度</param>
    /// <param name="isMove">箭头是否播放移动动画</param>
    /// <param name="moveRange">移动范围</param>
    /// <param name="isPingPong">是否PingPong动画</param>
    public void New_ShowFocusPointer(RectTransform focusRectTf, Canvas canvas, float angle, bool isMove, float moveRange, GuiClickTutorialNode.FingerType fingerType, bool isPingPong = true)
    {
        StartCoroutine(New_ShowFocusPointerSub(focusRectTf, canvas, angle, isMove, moveRange, fingerType, isPingPong));
    }

    IEnumerator New_ShowFocusPointerSub(RectTransform focusRectTf, Canvas canvas, float angle, bool isMove, float moveRange, GuiClickTutorialNode.FingerType fingerType, bool isPingPong = true)
    {
        if (new_focusPointer == null)
        {
            new_focusPointer = Instantiate(Resources.Load<TutorialPointer>("Prefabs/Tutorial/Focus/TutorialPointer")) as TutorialPointer;
            new_focusPointerRect = new_focusPointer.transform as RectTransform;
            new_focusPointerRect.SetParent(transform);
        }
        new_focusPointer.StartPoint(fingerType);

        //具体使用如下，target是你要参考坐标转换的目标对象
        var pos = focusRectTf.transform.TransformToCanvasLocalPosition(canvas);
        new_focusPointerRect.anchoredPosition = pos;

        angle = UIUtils.NormalizedAngle(angle);
		new_focusPointerRect.localScale = new Vector3(-1, angle > 90 && angle < 270 ? 1 : -1, 1);
        new_focusPointerRect.eulerAngles = new Vector3(0, 0, angle);

        yield return null;
    }

    /// <summary>
    /// <para>隐藏一个指示箭头</para>
    /// </summary>
    public void New_HideFocusPointer()
    {
        if (new_focusPointerRect)
        {
            new_focusPointer.Stop();
        }
    }

    /// <summary>
    /// <para>当前是否存在指示箭头</para>
    /// </summary>
    public bool New_HasFocusPointer()
    {
        return _focusPointerRect != null && _focusPointerRect.gameObject.activeInHierarchy;
    }

    #endregion

    #region    手指滑动
    /// <summary>
	/// <para>指示箭头对象</para>
	/// </summary>
	RectTransform FingerMoveRect = null;
    FingerMove fingerMove = null;

    /// <summary>
    /// <para>显示一个手指滑动</para>
    /// </summary>
    /// <param name="focusRectTf">遮罩不覆盖的UI元素的RectTransform组件</param>
    /// <param name="canvas">所属的canvas对象</param>
    /// <param name="angle">箭头指向角度</param>
    /// <param name="isMove">箭头是否播放移动动画</param>
    /// <param name="moveRange">移动范围</param>
    /// <param name="isPingPong">是否PingPong动画</param>
    public void ShowFingerMove(FingerMoveNode.moveInfo info, float startwaitTime, float moveTime, TutorialPointer.pointType startType, bool isPingPong = true)
    {
        if (fingerMove == null)
        {
            fingerMove = Instantiate(Resources.Load<FingerMove>("Prefabs/Tutorial/Focus/FingerMove")) as FingerMove;
            FingerMoveRect = fingerMove.transform as RectTransform;
            FingerMoveRect.SetParent(transform);
            FingerMoveRect.localScale = Vector3.one;
            FingerMoveRect.anchoredPosition = new Vector2(0, 0);
        }
        fingerMove.StartMove(info, startwaitTime, moveTime, startType, isPingPong);
        
    }

    /// <summary>
    /// <para>隐藏一个手指滑动</para>
    /// </summary>
    public void HideFingerMove()
    {
        if (fingerMove)
        {
            fingerMove.Stop();
        }
    }
    #endregion 手机滑动


    #region     两个遮罩的情况(临时代码)

    public const float height = 2000;
    public const float width = 3000;
    public enum Direction
    {
        left,
        right,
        top,
        down
    }

    List<Direction> directionList = new List<Direction>() { Direction.left, Direction.top, Direction.down, Direction.right };

    void MaskLeft(Rect left)
    {
        Vector2 pos = new Vector2(left.xMin - width / 2, left.yMin);
        Vector2 size = new Vector2(width, height);
        for (int i = 0; i < directionList.Count; i++)
        {
            switch (directionList[i])
            {
                case Direction.left:
                    pos = new Vector2(left.xMin - width / 2, left.yMin);
                    break;
                case Direction.right:
                    continue;
                case Direction.top:
                    pos = new Vector2(left.xMax - left.size.x / 2, left.yMax + height / 2);
                    size = new Vector2(left.size.x, height);
                    break;
                case Direction.down:
                    pos = new Vector2(left.xMax - left.size.x / 2, left.yMin - height / 2);
                    size = new Vector2(left.size.x, height);
                    break;
                default:
                    break;
            }
            SetAndGetMaskObj(pos, size);
        }
    }

    void SetAndGetMaskObj(Vector2 pos, Vector2 size)
    {
        RectTransform obj = GetMaskObject();
        obj.anchoredPosition = pos;
        obj.sizeDelta = size;
        obj.localScale = Vector3.one;
        twoUseMaskList.Enqueue(obj);
        obj.GetComponent<Image>().color = new Color(0, 0, 0, twoMaskAlpha);
    }

    void MaskLRCenter(Rect left, Rect right)
    {
        Vector2 pos = new Vector2(right.xMin + (left.xMax - right.xMin) / 2, left.yMin);
        Vector2 size = new Vector2(Mathf.Abs(left.xMax - right.xMin), height);
        SetAndGetMaskObj(pos, size);
    }

    void MaskRight(Rect right)
    {
        Vector2 pos = new Vector2(right.xMin - width / 2, right.yMin);


        for (int i = 0; i < directionList.Count; i++)
        {
            Vector2 size = new Vector2(width, height);
            switch (directionList[i])
            {
                case Direction.left:
                    continue;
                case Direction.right:
                    pos = new Vector2(right.xMax + size.x / 2, right.xMin);
                    break;
                case Direction.top:
                    pos = new Vector2(right.xMax - right.size.x / 2, right.yMax + height / 2);
                    size = new Vector2(right.size.x, height);
                    break;
                case Direction.down:
                    pos = new Vector2(right.xMax - right.size.x / 2, right.yMin - height / 2);
                    size = new Vector2(right.size.x, height);
                    break;
                default:
                    break;
            }
            SetAndGetMaskObj(pos, size);
        }
    }

    void MaskLeftRight(Rect left, Rect right)
    {
        MaskLeft(left);
        MaskRight(right);
        MaskLRCenter(left, right);
    }

    void MaskRectList(Rect left, Rect right)
    {
        if (left.xMax < right.xMin)
        {
            MaskLeftRight(left, right);
        }
        else if (right.xMax < left.xMin)
        {
            MaskLeftRight(right, left);

        }
        else if (right.yMax < left.yMin)
        {
            MaskRectTopDown(right, left);
        }
        else if (left.yMax < right.yMin)
        {
            MaskRectTopDown(left, right);
        }

    }

    Queue<RectTransform> twoUseMaskList = new Queue<RectTransform>();
    Queue<RectTransform> twoIdelMaskList = new Queue<RectTransform>();
    RectTransform GetMaskObject()
    {
        RectTransform retTrans;
        if (twoIdelMaskList.Count > 0)
        {
            retTrans = twoIdelMaskList.Dequeue();
            retTrans.gameObject.SetActive(true);
        }
        else
        {
            var obj = new GameObject();
            obj.transform.SetParent(transform);
            var image = obj.AddComponent<Image>();
            retTrans = obj.transform as RectTransform;
        }
        return retTrans;
    }

    public void ShowTwoMask(RectTransform a, RectTransform b, Canvas canvas)
    {
        Rect ar = GetRect(a, canvas);
        Rect br = GetRect(b, canvas);
        if (ar.Overlaps(br))
        {
            Debug.LogError(string.Format(" rect transform are overlab, namea: {0}, nameb: {1}", a.name, b.name));
            return;
        }
        MaskRectList(ar, br);
    }

    public float twoMaskAlpha = 0f;
    public void ShowTwoMask(Rect ar, Rect br, Canvas canvas, float alpha)
    {
        twoMaskAlpha = alpha;
        if (ar.Overlaps(br))
        {
            Debug.LogError(" rect are overlab");
            return;
        }
        MaskRectList(ar, br);
    }

    public void HideTwoMask()
    {
        while (twoUseMaskList.Count > 0)
        {
            var obj = twoUseMaskList.Dequeue();
            obj.gameObject.SetActive(false);
            twoIdelMaskList.Enqueue(obj);
        }
    }

    void MaskTop(Rect top)
    {
        Vector2 pos = new Vector2(top.xMin - width / 2, top.yMin);

        for (int i = 0; i < directionList.Count; i++)
        {
            Vector2 size = new Vector2(width, height);
            switch (directionList[i])
            {
                case Direction.left:
                    continue;
                case Direction.right:
                    pos = new Vector2(top.center.x, top.yMax + size.y / 2);
                    break;
                case Direction.top:
                    pos = new Vector2(top.xMin - size.x / 2, top.center.y);
                    size = new Vector2(width, top.size.y);
                    break;
                case Direction.down:
                    pos = new Vector2(top.xMax + size.x / 2, top.center.y);
                    size = new Vector2(width, top.size.y);
                    break;
                default:
                    break;
            }
            SetAndGetMaskObj(pos, size);
        }
    }

    void MaskTDCenter(Rect top, Rect down)
    {
        Vector2 pos = new Vector2(top.center.x, down.yMax + (top.yMin - down.yMax) / 2);
        Vector2 size = new Vector2(width, top.yMin - down.yMax);
        GameObject obj = new GameObject();
        SetAndGetMaskObj(pos, size);
    }

    void MaskDown(Rect down)
    {
        Vector2 pos = new Vector2(down.xMin - width / 2, down.yMin);


        for (int i = 0; i < directionList.Count; i++)
        {
            Vector2 size = new Vector2(width, height);
            switch (directionList[i])
            {
                case Direction.left:
                    pos = new Vector2(down.center.x, down.yMin - size.y / 2);
                    break;
                case Direction.right:
                    continue;
                case Direction.top:
                    pos = new Vector2(down.xMin - size.x / 2, down.center.y);
                    size = new Vector2(width, down.size.y);
                    break;
                case Direction.down:
                    pos = new Vector2(down.xMax + size.x / 2, down.center.y);
                    size = new Vector2(width, down.size.y);
                    break;
                default:
                    break;
            }
            SetAndGetMaskObj(pos, size);
        }
    }

    void MaskRectTopDown(Rect down, Rect top)
    {
        MaskDown(down);
        MaskTop(top);
        MaskTDCenter(top, down);
    }   

    public Rect GetRect(RectTransform rectTrans, Canvas canvas)
    {
        Vector2 canvasScale = canvas.transform.localScale;
        var posa = rectTrans.transform.TransformToCanvasLocalPosition(canvas);
        Vector2 asize = new Vector2(rectTrans.rect.size.x , rectTrans.rect.size.y);
        //Vector2 asize = new Vector2(rectTrans.rect.size.x , rectTrans.rect.size.y);
        Rect ar = new Rect(posa.x - asize.x / 2, posa.y - asize.y / 2, asize.x, asize.y);
        return ar;
    }

    #endregion  两个遮罩的情况(临时代码)




    /// <summary>
    /// 设置提示框得大小
    /// </summary>
    /// <param name="point"></param>
    /// <param name="showType"></param>
    /// <returns></returns>
    public IEnumerator SetPromptSize(Vector2 point, PromptType showType)
    {
        yield return new WaitForEndOfFrame();
        var box = tutorialPromptBox.Find("box").GetComponent<RectTransform>();
        var text = box.transform.Find("text").GetComponent<Text>();
        var angle = box.transform.Find("angle").GetComponent<RectTransform>();

        var transRect = box.GetComponent<RectTransform>();
        transRect.anchoredPosition = GetPositionWithPercent(point);
        transRect.sizeDelta = new Vector2(text.preferredWidth + 40, text.preferredHeight + 40);
        angle.gameObject.SetActive(true);
        switch (showType)
        {
            case PromptType.Left:
                angle.localEulerAngles = new Vector3(0, 0, 90);
                angle.anchoredPosition = new Vector2(-(transRect.sizeDelta.x / 2 - 4 + 10), 0);
                break;
            case PromptType.Right:
                angle.localEulerAngles = new Vector3(0, 0, 270);
                angle.anchoredPosition = new Vector2((transRect.sizeDelta.x / 2 - 4 + 10), 0);
                break;
            case PromptType.Up:
                angle.anchoredPosition = new Vector2(0, (transRect.sizeDelta.y / 2 - 2 + 10));
                angle.localEulerAngles = new Vector3(0, 0, 0);
                break;
            case PromptType.Down:
                angle.anchoredPosition = new Vector2(0, -(transRect.sizeDelta.y / 2 - 2 + 10));
                angle.localEulerAngles = new Vector3(0, 0, 180);
                break;
            case PromptType.Hide:
                angle.gameObject.SetActive(false);
                break;
            default:
                break;
        }
    }

    /// <summary>
    /// 展示泡泡提示框
    /// </summary>
    /// <param name="showText"> 展示文字 </param>
    /// <param name="point"> 图片位置, 以比列配置</param>
    /// <param name="parent"> 不传的默认以Manager的为节点</param>
    /// <returns></returns>
    public void ShowPromptBox(string showText, Canvas rootCanvas,Vector2 point, PromptType showType, bool move, float range)
    {
        if(tutorialPromptBox == null)
        {
            var go = Instantiate(Resources.Load<GameObject>("Prefabs/UI/Tutorial/TutorialPromptBox")) as GameObject;
            tutorialPromptBox = go.transform as RectTransform;
            tutorialPromptBox.SetParent(transform, false);
            tutorialPromptBox.localScale = Vector3.one;
        }
        tutorialPromptBox.gameObject.SetActive(true);
        var text = tutorialPromptBox.Find("box/text").GetComponent<Text>();
        text.text = showText.Replace("\\n", "\n");
        StartCoroutine(SetPromptSize(point, showType));
        

        if (move)
        {
            var moveDirection = UIUtils.GetNormalizedFromAngle(90);
            Vector2 targetPosition = (Vector2)tutorialPromptBox.position - moveDirection * range * rootCanvas.transform.localScale.x;
            GameObjectMove(tutorialPromptBox.gameObject, tutorialPromptBox.position, targetPosition, 1, true);
        }

    }


    public void HidePromptBox()
    {
        if(tutorialPromptBox != null)
        {
            tutorialPromptBox.gameObject.SetActive(false);
        }
    }

    public Vector3 GetPositionWithPercent(Vector2 percent)
    {
        var parent = transform.parent;
        var canvasRect = parent.GetComponent<RectTransform>();
        float pointx = (percent.x * 2 - 1) * canvasRect.sizeDelta.x * 0.5f;
        float pointy = (percent.y * 2 - 1) * canvasRect.sizeDelta.y * 0.5f;
        return new Vector2(pointx , pointy);

    }

    /// <summary>
    /// 加载图片
    /// </summary>
    /// <param name="spritePath"> 图片路径 </param>
    /// <param name="point"> 图片位置和大小， x，y为位置， width，height为大小， 以比列配置</param>
    /// <param name="parent"> 不传的默认以Manager的为节点</param>
    /// <returns></returns>
    public Image LoadImage(string spritePath, Rect point, Transform parent = null) {
        parent = parent == null ? transform.parent : parent;
        var canvasRect = parent.GetComponent<RectTransform>(); 
        GameObject obj = new GameObject();
        obj.transform.parent = parent;
        Image image = obj.AddComponent<Image>();
        image.sprite = Resources.Load<Sprite>(UITools.GetResourcePath(spritePath));
        var rect = image.GetComponent<RectTransform>();
        float width = 0, height = 0;

        if(point.width == 0 && point.height == 0)
        {
            image.SetNativeSize();
            width = image.rectTransform.sizeDelta.x;
            height = image.rectTransform.sizeDelta.x;
        }else
        {
            width = point.width * canvasRect.sizeDelta.x;
            height = point.height * canvasRect.sizeDelta.y;
        }

        

        rect.anchorMax = Vector2.one;
        rect.anchorMin = Vector2.zero;
        rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
        rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
        float pointx = (point.x * 2 - 1) * canvasRect.sizeDelta.x * 0.5f;
        float pointy = (point.y * 2 - 1) * canvasRect.sizeDelta.y * 0.5f;


        rect.anchoredPosition = new Vector2(pointx + width / 2, pointy + height / 2);

        

        return image;
    }

	#region 图片动画，基于两点

	/// <summary>
	/// <para>基于两点来回移动的图片动画</para>
	/// </summary>
	/// <param name="go">物体对象</param>
	/// <param name="startPoint">起始点</param>
	/// <param name="targetPoint">目标点</param>
	/// <param name="speed">移动速度</param>
	/// <param name="isPingPong">是否PingPong动画</param>
	public void GameObjectMove(GameObject go, Vector2 startPoint, Vector2 targetPoint, float speed = 1f, bool isPingPong = false)
	{
		StartCoroutine(GameObjectMoveSub(go, startPoint, targetPoint, speed, isPingPong));
	}

	IEnumerator GameObjectMoveSub(GameObject go, Vector2 startPoint, Vector2 targetPoint, float speed, bool isPingPong = false)
	{
		float progress = 0;
		bool isToTarget = true;
		while (go && go.activeSelf) {
			if (isPingPong) {
				if (isToTarget)
					progress += speed * Time.deltaTime;
				else
					progress -= speed * Time.deltaTime * 2;//收回速度加倍
			} else
				progress += speed * Time.deltaTime;

			var target = go.GetComponent<RectTransform>();
			target.transform.position = Vector2.Lerp(startPoint, targetPoint, progress);
			//UIUtils.SetScreenPosition (ref target, GetCanvas (), Vector2.Lerp (startPoint, targetPoint, progress));
			if (isPingPong) {
				if (progress >= 1)
					isToTarget = false;
				else if (progress <= 0)
					isToTarget = true;
			} else {
				if (progress >= 1) {
					progress = 0;
					yield return new WaitForSeconds(0.4f);
				}
			}
			yield return null;
		}
	}

	#endregion
}
